package NWish
{
	import NWish.Interface.IApp;
	import NWish.Interface.ILogger;
	
	import away3d.core.base.Object3D;
	
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.ui.Keyboard;
	
	import org.aswing.JToggleButton;
	import org.aswing.event.AWEvent;
	
	
	
	
	public class TransformEdit
	{
		private var _parent:IApp;
		
		private var _transformToggleButton:JToggleButton;

		public function TransformEdit(parent:IApp)
		{
			//
			_parent = parent;
			
			//
			var menuBar:MenuBar = _parent.getPlugin('MenuBar') as MenuBar;
			menuBar.settingMenu.addMenuItem("&TransformEdit setting").addActionListener(_showSetting);
		
			//
			_parent.KBEventDispatcher.addEventListener(KeyboardEvent.KEY_DOWN, 		onKeyDown);
			_parent.KBEventDispatcher.addEventListener(KeyboardEvent.KEY_UP, 		onKeyUp);
			
			_parent.away3d.addEventListener(MouseEvent.MOUSE_DOWN, 		onMouseDown);
			_parent.away3d.addEventListener(MouseEvent.MOUSE_MOVE, 		onMouseMove);
			_parent.away3d.addEventListener(MouseEvent.MOUSE_WHEEL, 	onMouseWheel);
			
			//
			_parent.NWEventDispatcher.addEventListener(NWEvent.SELSCT_OBJECT,onSelectObject);
		}
		
		public function init()
		{	
			//
			var menuBar:MenuBar = _parent.getPlugin('MenuBar') as MenuBar;
			_transformToggleButton = new JToggleButton("transform");
			_transformToggleButton.y = 2;
			_transformToggleButton.setToolTipText('Hot key 2 is active. Hot ket QWE is move pos. Hot ASD is rotation, hot ZXCV is scale.');
			menuBar.addButton(_transformToggleButton,'Group0',Keyboard.NUMBER_2);//` key code is 192
			
		}
		
		private function get isSelected()
		{
			return _transformToggleButton.isSelected();
		}
		
		private function _showSetting(e)
		{
			ILogger.log('todo ...');
		}
		
		public function get scene()
		{
			var away3d = _parent.getPlugin('Away3d');
			return away3d.view.scene;
		}
		
		//
		private var _q = false;//key code 81
		private var _w = false;//key code 87
		private var _e = false;//key code 69
		private var _a = false;//key code 65
		private var _s = false;//key code 83
		private var _d = false;//key code 68
		private var _z = false;//key code 90
		private var _x = false;//key code 88
		private var _c = false;//key code 67
		private var _v = false;
		
		public function onKeyDown(e:KeyboardEvent)
		{
			if( isSelected == false  || e.ctrlKey || e.shiftKey)
				return;
			
			if(_q || _w || _e || _a || _s || _d || _z || _x || _c || _v)
				return;
			
			_mouseWheeling = false;
			
			var k;
			if(e.keyCode == Keyboard.Q)
			{
				_q = true;
				k = 'x';
			}
			else if(e.keyCode == Keyboard.W)
			{
				_w = true;
				k = 'y';
			}
			else if(e.keyCode == Keyboard.E)
			{
				_e = true;
				k = 'z';
			}
			else if(e.keyCode == Keyboard.A)
			{
				_a = true;
				k = 'rotationX';
			}
			else if(e.keyCode == Keyboard.S)
			{
				_s = true;
				k = 'rotationY';
			}
			else if(e.keyCode == Keyboard.D)
			{
				_d = true;
				k = 'rotationZ';
			}
			else if(e.keyCode == Keyboard.Z)
			{
				_z = true;
				k = 'scale';
			}
			else if(e.keyCode == Keyboard.X)
			{
				_x = true;
				k = 'scaleX';
			}
			else if(e.keyCode == Keyboard.C)
			{
				_c = true;
				k = 'scaleY';
			}
			else if(e.keyCode == Keyboard.V)
			{
				_v = true;
				k = 'scaleZ';
			}
			
			
			_lastX = _parent.rootSprite.stage.mouseX;
			_lastY = _parent.rootSprite.stage.mouseY;
			
			if(k)
			{
				for each(var o in _selectObjects)
				{
					if(o is Object3D)
					{
						var o_:Object3D = o as Object3D;
						if(o_.extra == null)
							o_.extra = new Object();
						
						o_.extra.lastTF = new Object();
						
						if(k == 'scale')
						{
							o_.extra.lastTF['scaleX'] = o_['scaleX'];
							o_.extra.lastTF['scaleY'] = o_['scaleY'];
							o_.extra.lastTF['scaleZ'] = o_['scaleZ'];
						}
						else
						{
							o_.extra.lastTF[k] = o_[k];
						}
					}
				}
			}
		}
		
		public function onKeyUp(e:KeyboardEvent)
		{
			if( isSelected == false  || e.ctrlKey || e.shiftKey)
				return;
			
			if(e.keyCode == Keyboard.Q)_q = false;
			else if(e.keyCode == Keyboard.W)_w = false;
			else if(e.keyCode == Keyboard.E)_e = false;
			else if(e.keyCode == Keyboard.A)_a = false;
			else if(e.keyCode == Keyboard.S)_s = false;
			else if(e.keyCode == Keyboard.D)_d = false;
			else if(e.keyCode == Keyboard.Z)_z = false;
			else if(e.keyCode == Keyboard.X)_x = false;
			else if(e.keyCode == Keyboard.C)_c = false;
			else if(e.keyCode == Keyboard.V)_v = false;
			
			//
			for each(var o in _selectObjects)
			{
				if(o is Object3D)
				{
					var o_:Object3D = o as Object3D;
					
					if(o_.extra['lastTF'] == null)
						return;
				}
			}
			
			//
			_parent.getPlugin('UndoManager').addDo(new Do(_selectObjects,_parent));
			
			//
			for each(var o in _selectObjects)
			{
				if(o is Object3D)
				{
					var o_:Object3D = o as Object3D;
					
					o_.extra['lastTF'] = null;
					
					if(o_ == _parent.getPlugin('PropertiesExplorer').currObject)
					{
						_parent.getPlugin('PropertiesExplorer').currObject = o_;
					}
				}
			}
		}
		
		private var _posSpeed = 0.5;
		private var _rotationSpeed = 0.1;
		private var _scaleSpeed = 0.01;
		
		private var _lastX;
		private var _lastY;
		public function onMouseMove(e:MouseEvent)
		{
			if( isSelected == false || e.ctrlKey)
				return;
			
			if(_mouseWheeling)
				return;
			
			var x = _lastX - e.stageX;
			var y = _lastY - e.stageY;
			_lastX = e.stageX;
			_lastY = e.stageY;
			
			transform(x,y);
		}
		
		public var move_offset = 100;
		public var scale_offset = 0.1;
		public var rotation_offset = 45;
		private var _mouseWheeling = false;
		public function onMouseWheel(e:MouseEvent)
		{
			if( isSelected == false || e.ctrlKey)
				return;

			if(_mouseWheeling == false)
			{
				_mouseWheeling = true;
				cancelTF();
			}
			
			var x = e.delta;
			
			if(_q || _w || _e)
			{
				if(x > 0)
					x = move_offset;
				else
					x = -move_offset;
			}
			else
			if(_a || _s || _d)
			{
				if(x > 0)
					x = rotation_offset;
				else
					x = -rotation_offset;
			}
			else
			if( _z || _x || _c || _v)
			{
				if(x > 0)
					x = scale_offset;
				else
					x = -scale_offset;
			}
			
			//ILogger.log(x);
			
			transform(x);
		}
		
		public function onMouseDown(e:MouseEvent)
		{
			if(isSelected == false)
				return;
			
			if(_q || _w || _e || _a || _s || _d || _z || _x || _c || _v)
			{
				cancelTF();
			}
		}
		
		private function cancelTF()
		{
			for each(var o in _selectObjects)
			{
				if(o is Object3D)
				{
					var o_:Object3D = o as Object3D;
					
					if(o_.extra['lastTF'] == null)
						return;//throw new Error();
					
					for(var k in o_.extra.lastTF)
					{
						o_[k] = o_.extra.lastTF[k];
					}
					
					if(o_.scaleX == 0 || o_.scaleY == 0 || o_.scaleZ == 0)
						throw new Error();
				}
			}
		}
		
		//
		private var _selectObjects;
		private function onSelectObject(e:NWEvent)
		{
			_selectObjects = e.objects;
			if(_selectObjects is Array == false)
				_selectObjects = [_selectObjects];
		}
		
		private function transform(x,y = null)
		{
			if(_q)
			{
				for each(var o in _selectObjects)
				{
					if(o is Object3D)
					{
						var o_:Object3D = o as Object3D;
						if(y != null)
						{
							o_.x += x * _posSpeed;
							o_.x += y * _posSpeed * 2;
						}
						else
						{
							o_.x += x;
						}
					}
				}
			}
			else if(_w)
			{
				for each(var o in _selectObjects)
				{
					if(o is Object3D)
					{
						var o_:Object3D = o as Object3D;
						if(y != null)
						{
							o_.y += x * _posSpeed;
							o_.y += y * _posSpeed * 2;
						}
						else
						{
							o_.y += x;
						}
					}
				}
			}
			else if(_e)
			{
				for each(var o in _selectObjects)
				{
					if(o is Object3D)
					{
						var o_:Object3D = o as Object3D;
						if(y != null)
						{
							o_.z += x * _posSpeed;
							o_.z += y * _posSpeed * 2;
						}
						else
						{
							o_.z += x;
						}
					}
				}
			}
			else if(_a)
			{
				for each(var o in _selectObjects)
				{
					if(o is Object3D)
					{
						var o_:Object3D = o as Object3D;
						if(y != null)
						{
							o_.rotationX += x * _rotationSpeed;
							//o_.rotationX += y;
						}
						else
						{
							o_.rotationX += x;
						}
					}
				}
			}
			else if(_s)
			{
				for each(var o in _selectObjects)
				{
					if(o is Object3D)
					{
						var o_:Object3D = o as Object3D;
						if(y != null)
						{
							o_.rotationY += x * _rotationSpeed;
							//o_.rotationY += y;
						}
						else
						{
							o_.rotationY += x;
						}
					}
				}
			}
			else if(_d)
			{
				for each(var o in _selectObjects)
				{
					if(o is Object3D)
					{
						var o_:Object3D = o as Object3D;
						if(y != null)
						{
							o_.rotationZ += x * _rotationSpeed;
							//o_.rotationZ += y;
						}
						else
						{
							o_.rotationZ += x;
						}
					}
				}
			}
			else if(_z)
			{
				for each(var o in _selectObjects)
				{
					if(o is Object3D)
					{
						var o_:Object3D = o as Object3D;
					
						var sx = o_.scaleX;
						var sy = o_.scaleY;
						var sz = o_.scaleZ;
						
						if(y != null)
						{
							o_.scaleX += x * _scaleSpeed;
							//o_.scaleX += y;
							o_.scaleY += x * _scaleSpeed;
							//o_.scaleY += y;
							o_.scaleZ += x * _scaleSpeed;
							//o_.scaleZ += y;
							
							//trace(x * _scaleSpeed);
						}
						else
						{
							o_.scaleX += x;
							o_.scaleY += x;
							o_.scaleZ += x;
						}
						
						if(o_.scaleX == 0) o_.scaleX = sx;
						if(o_.scaleY == 0) o_.scaleY = sy;
						if(o_.scaleZ == 0) o_.scaleZ = sz;
					}
				}
			}
			else if(_x)
			{
				for each(var o in _selectObjects)
				{
					if(o is Object3D)
					{
						var o_:Object3D = o as Object3D;
						
						
						var sx = o_.scaleX;
						
						if(y != null)
						{
							o_.scaleX += x * _scaleSpeed;
							//o_.scaleX += y;
						}
						else
						{
							o_.scaleX += x;
						}
						
						if(o_.scaleX == 0) o_.scaleX = sx;
					}
				}
			}
			else if(_c)
			{
				for each(var o in _selectObjects)
				{
					if(o is Object3D)
					{
						var o_:Object3D = o as Object3D;
						
						var sy = o_.scaleY;
						
						if(y != null)
						{
							o_.scaleY += x * _scaleSpeed;
							//o_.scaleY += y;
						}
						else
						{
							o_.scaleY += x;
						}
						
						if(o_.scaleY == 0) o_.scaleY = sy;
					}
				}
			}
			else if(_v)
			{
				for each(var o in _selectObjects)
				{
					if(o is Object3D)
					{
						var o_:Object3D = o as Object3D;
						
						var sz = o_.scaleZ;
						
						if(y != null)
						{
							o_.scaleZ += x * _scaleSpeed;
							//o_.scaleZ += y;
						}
						else
						{
							o_.scaleZ += x;
						}
					
						
						if(o_.scaleZ == 0) o_.scaleZ = sz;
					}
				}
			}
		}
	}
}


import away3d.core.base.Object3D;


class Do
{
	private var _parent;
	private var _objects;
	private var _undoTFs:Array = [];
	private var _redoTFs:Array;
	
		
	public function Do(objects,parent)
	{
		_parent = parent;
		
		_objects = objects;
		
		for each(var o in objects)
		{
			if(o is Object3D)
			{
				var o_:Object3D = o as Object3D;
				
				if(o_.extra['lastTF'] == null)
					throw new Error();
				
				_undoTFs.push(o_.extra['lastTF']);
			}
			else
			{
				_undoTFs.push(null);
			}
		}
	}
	
	public function undo()
	{
		_redoTFs = [];
		var i = 0;
		for each(var o in _objects)
		{
			if(o is Object3D)
			{
				var o_:Object3D = o as Object3D;
				var tf = _undoTFs[i];
				
				var newTF = new Object();
				
				for(var k in tf)
				{
					newTF[k] = o_[k];
					o_[k] = tf[k];
				}
				
				if(o_ == _parent.getPlugin('PropertiesExplorer').currObject)
				{
					_parent.getPlugin('PropertiesExplorer').currObject = o_;
				}
				
				_redoTFs.push(newTF);
			}
			else
			{
				_redoTFs.push(null);
			}
			
			++i;
		}
	}
	public function redo()
	{
		var i = 0;
		for each(var o in _objects)
		{
			if(o is Object3D)
			{
				var o_:Object3D = o as Object3D;
				var tf = _redoTFs[i];
				
				for(var k in tf)
				{
					o_[k] = tf[k];
				}
				
				
				if(o_ == _parent.getPlugin('PropertiesExplorer').currObject)
				{
					_parent.getPlugin('PropertiesExplorer').currObject = o_;
				}
				
			}
			
			++i;
		}
	}
}



